package com.selenium.core.functionlibrary;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;

import jxl.Cell;

import org.apache.commons.validator.GenericValidator;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

/**
 * Performs read/write operations on files
 * 
 * @author phebbar
 * 
 */
public class FileHandler {

	/**
	 * Retrieves the data from the properties file using variable name.
	 * 
	 * @param path
	 *            to Property file.
	 * @param variableName
	 *            stored in the properties file.
	 * 
	 * @return value of property
	 * @throws Exception
	 */

	public static String getDataFromPropertiesFile(String path,
			String variableName) throws Exception {

		Properties props = new Properties();
		props.load(new FileInputStream(path));
		String propertyFileData = props.getProperty(variableName);
		/*
		 * Found any value returns the data else returns null.
		 */
		if (!GenericValidator.isBlankOrNull(propertyFileData)) {
			return propertyFileData;
		} else {
			return null;
		}
	}

	/**
	 * Retrieves the Excel cell value based on the row and column number.
	 * 
	 * @param path
	 * @param sheetNumber
	 * @param rowNumber
	 * @param col
	 * @return cell value
	 * @throws Exception
	 */
	public static String readExcelData(String path, int sheetNumber,
			int rowNumber, int col) throws Exception {
		jxl.Workbook workbook = jxl.Workbook.getWorkbook(new File(path));
		jxl.Sheet sheet = workbook.getSheet(sheetNumber);
		jxl.Cell a12 = (jxl.Cell) sheet.getCell(col, rowNumber);
		String cellValue = ((jxl.Cell) a12).getContents();
		return cellValue;
	}

	/**
	 * Writes the provided value to the Excel cell based on the row and column
	 * number.
	 * 
	 * @param path
	 * @param rowNumber
	 * @param col
	 * @param addDataToCell
	 * @throws Exception
	 */
	@SuppressWarnings("deprecation")
	public static void writeToExcel(String path, String sheetName,
			int rowNumber, int col, String addDataToCell) throws Exception {

		HSSFWorkbook workbook = new HSSFWorkbook();
		FileOutputStream output = new FileOutputStream(path);
		HSSFSheet sheet = workbook.createSheet(sheetName);
		HSSFRow row = sheet.createRow((short) rowNumber);
		HSSFCell cell = row.createCell((short) col);

		// Providing the value which is to be added in the Excel.
		cell.setCellValue(addDataToCell);
		workbook.write(output);
	}

	/**
	 * Retrieves single row data based on the row number
	 * 
	 * @param path
	 * @param sheetNumber
	 * @param rowNumber
	 * @return cell values of a single row
	 * @throws Exception
	 */

	public static ArrayList<String> getRowDataFromExcel(String path,
			int sheetNumber, int rowNumber, int startColNumber)
			throws Exception {
		ArrayList<String> cellContent1 = new ArrayList<String>();
		jxl.Workbook workbook = null;
		jxl.Sheet sheet = null;
		workbook = jxl.Workbook.getWorkbook(new File(path));
		sheet = workbook.getSheet(sheetNumber);

		int cols = 0;// Initializing column number.
		cols = sheet.getColumns();

		for (int i = startColNumber; i < cols; i++) { // getting all the Row
			// values

			Cell value = sheet.getCell(i, rowNumber);
			// Values are retrieved when cell value is not null.
			if (value.getContents() != null) {
				cellContent1.add(value.getContents());

			}
		}
		return cellContent1;
	}

	/**
	 * Retrieves column data based on the row number
	 * 
	 * @param path
	 * @param sheetNumber
	 * @param colNumber
	 * @param startRowNumber
	 * @return cell values of a single column
	 * @throws Exception
	 */
	public static ArrayList<String> getColumnDataFromExcel(String path,
			int sheetNumber, int colNumber, int startRowNumber)
			throws Exception {
		ArrayList<String> cellContents1 = new ArrayList<String>();
		jxl.Workbook workbook = null;
		jxl.Sheet sheet = null;
		workbook = jxl.Workbook.getWorkbook(new File(path));
		sheet = workbook.getSheet(sheetNumber);

		int rows = 0;
		rows = sheet.getRows();

		for (int i = startRowNumber; i < rows; i++) { // Retrieving values based
			// on column number and
			// starting row number.
			Cell value = sheet.getCell(colNumber, i);
			// Values are retrieved when cell contents are not null.
			if (value.getContents() != null) {
				cellContents1.add(value.getContents());
			}
		}
		return cellContents1;
	}

	/**
	 * Provides the cell type of a cell whether its a Numeric, string, Formula,
	 * blank cell etc.
	 * 
	 * @param cell
	 * @return cell type based on the cell
	 * @throws Exception
	 */

	public static String cellToString(HSSFCell cell) throws Exception {
		int type = cell.getCellType();
		Object result;
		switch (type) {
		case HSSFCell.CELL_TYPE_NUMERIC: // 0 cell type is Numeric

			// Returns Numeric value along with decimal values
			String result_double = (new Double(cell.getNumericCellValue())
					.toString());

			// Returns an Integer value truncating decimal values
			if (result_double.endsWith(".0")) {
				result = (int) java.lang.Math.round(Double
						.parseDouble((result_double)));
			} else
				result = result_double;
			break;

		case HSSFCell.CELL_TYPE_STRING: // 1 cell type is string
			result = cell.getStringCellValue();
			break;

		case HSSFCell.CELL_TYPE_FORMULA: // 2 cell type is formula
			result = cell.getStringCellValue();
			break;

		case HSSFCell.CELL_TYPE_BLANK: // 3 cell type is blank
			result = "";
			break;

		case HSSFCell.CELL_TYPE_BOOLEAN: // 4 cell type is boolean
			result = cell.getBooleanCellValue();
			break;

		case HSSFCell.CELL_TYPE_ERROR: // 5
			throw new RuntimeException("This cell has an error");
		default:
			throw new RuntimeException("We don't support this cell type: "
					+ type);
		}
		return result.toString();
	}

	/**
	 * Gets the columns in csv file
	 * 
	 * @param filePath
	 * @return
	 */
	public static List<String> getColumns(String filePath) {
		List<String> colnames = new ArrayList<String>();
		try {

			BufferedReader br = new BufferedReader(new InputStreamReader(
					new FileInputStream(new File(filePath))));
			String sLine = "";
			int rownumber = 0;
			StringTokenizer st = null;

			for (int columnnumber = 1; columnnumber < 2; columnnumber++) {
				sLine = br.readLine();
				if (sLine != null) {

					st = new StringTokenizer(sLine, ",");
					while (st.hasMoreTokens()) {
						rownumber++;
						String columnval = st.nextToken();
						if (columnnumber == 1) {
							colnames.add(columnval);
						}
					}
					rownumber = 0;
				}
			}
			return colnames;

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return colnames;

	}

	/**
	 * 
	 * Reads CSV data in to HashMap
	 * 
	 * @param filePath
	 * @return
	 */
	public static HashMap<String, Object[]> readcsv(String filePath) {

		HashMap<String, Object[]> Datamap = new HashMap<String, Object[]>();

		List<String> colnames = getColumns(filePath);
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(
					new FileInputStream(new File(filePath))));
			String sLine = "";
			int columnnumber = 0, rownumber = 0;
			StringTokenizer st = null;
			List<Object[]> Setlist = new ArrayList<Object[]>();
			while ((sLine = br.readLine()) != null) {
				rownumber++;
				List<Object> Data = new ArrayList<Object>();
				st = new StringTokenizer(sLine, ",");
				while (st.hasMoreTokens()) {
					columnnumber++;
					Data.add(st.nextToken());
				}

				Object[] eachdataset = new Object[columnnumber];
				for (int j = 0; j < columnnumber; j++) {
					eachdataset[j] = Data.get(j);
				}
				Setlist.add(eachdataset);
				columnnumber = 0;
			}

			// This part is to prepare the hash map

			int sizeofcolarray = Setlist.size() - 1;

			for (int columnnum = 0; columnnum < colnames.size(); columnnum++) {
				String nameofcolumn = colnames.get(columnnum);
				Object[] columndata = new Object[sizeofcolarray];
				for (int rownum = 1; rownum < Setlist.size(); rownum++) {
					Object[] eachrow = Setlist.get(rownum);
					columndata[rownum - 1] = eachrow[columnnum];
				}
				Datamap.put(nameofcolumn, columndata);
			}

			return Datamap;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;

	}

	/**
	 * Returns Data from the Notepad
	 * 
	 * @param path
	 * 
	 * 
	 * @return data or null
	 * @throws IOException
	 */

	public static String readFromNotepad(String path) throws IOException {
		FileReader input = new FileReader(path);
		BufferedReader in2 = new BufferedReader(input);
		String content = in2.readLine();
		/* Retrieving the contents when not null else returns null */
		if (content != null) {
			return content;
		} else
			return null;
	}

	/**
	 * Writes the contents into Notepad.
	 * 
	 * @param path
	 * @param text
	 * @throws Exception
	 */

	public static void writeContentsToNotepad(String path, String text)
			throws Exception {
		FileWriter fstream = new FileWriter(path, true);
		BufferedWriter out = new BufferedWriter(fstream);
		out.write(text);
		out.close();
	}

	/**
	 * Retrieves contents from Word document
	 * 
	 * @param path
	 * 
	 * @return content or null
	 * @throws Exception
	 */
	public static String readFromWordDoc(String path) throws Exception {
		FileReader fr = new FileReader(path);
		BufferedReader br = new BufferedReader(fr);
		String s = br.readLine(); // Reading the contents from word doc

		if (s != null) // Word doc has some data
			return s;
		else
			return null;
	}

	/**
	 * Writes the content to Word document.
	 * 
	 * @param path
	 * @param addText
	 * @throws Exception
	 */
	public static void writeToWordDoc(String path, String addText)
			throws Exception {
		FileOutputStream fs = new FileOutputStream(path);
		OutputStreamWriter out = new OutputStreamWriter(fs);
		out.write(addText);
		// out.append(addText);
		out.close();
	}

}
